package org.semanticflash.rdf.script
{
	

	import flash.events.EventDispatcher;
	
	import org.semanticflash.rdf.triple.RDFTriple;
	import org.semanticflash.rdf.values.IRDFValueHolder;
	import org.semanticflash.rdf.values.IRI;
	import org.semanticflash.rdf.values.RDFValue;




	/**
	 * 
	 * Provides a node centric API to work with RDF Graphs.
	 * 
	 * @author aldo.bucchi@gmail.com
	 * 
	 */
	public class RDFNode extends EventDispatcher implements IRDFValueHolder
	{
		


		//////////////////////////////////////
		// factory
		//////////////////////////////////////		

		private var _factory:RDFNodeFactory;
		
		public function get factory( ):RDFNodeFactory
		{
			return _factory;					
		}		



		/////////////////////////////////////
		// proxy
		/////////////////////////////////////
		
		private var _proxy:RDFNodeProxy;
		
		public function get proxy( ):RDFNodeProxy
		{
			if ( ! _proxy )
				_proxy = new RDFNodeProxy( this );
			return _proxy;
		}



		//////////////////////////////////////
		// rdfValue
		//////////////////////////////////////
		
		private var _rdfValue:RDFValue;
		
		public function get rdfValue( ):RDFValue
		{
			return _rdfValue;
		}
		
		
		//////////////////////////////////////
		// as3value
		//////////////////////////////////////
		[Bindable("as3ValueChanged")] // never changes
		public function get as3Value( ):*
		{
			return _rdfValue.as3Value;
		}		
		


		//////////////////////////////////////
		// constructor
		//////////////////////////////////////
		
		public function RDFNode( factory:RDFNodeFactory, rdfValue:RDFValue )
		{
			
			_factory = factory;
			_rdfValue = rdfValue;
		}

		
		
			

		/**
		 * 
		 * @param arc
		 * @param inverse
		 * @return 
		 * 
		 */	
		public function all( arc:IRI, inverse:Boolean = false ):Array
		{

			var result:Array = [ ];
			var s:RDFValue, o:RDFValue;
			// for now we are only using array providers
			// TODO: indexes ( we are only testing the scripting API for now )

			for each ( var triple:RDFTriple in factory.provider )
			{
				
				if ( triple.p != arc )					
					continue;
				
				s = inverse ? triple.o : triple.s;
				o = inverse ? triple.s : triple.o;
				
				if ( s == rdfValue )
					result.push( factory.getNode( o ) );		
				
			}
			
			return result;

//			var mask:RDFTriple = getTriple( _rdfTerm, arc, null );
//			var triples:Array = factory.provider.getTriples( inverse ? mask.inverse : mask ).asArray;		
//			var result:Array = [ ];
//			
//			for each ( var triple:RDFTriple in triples )
//			{
//				var term:RDFTerm = inverse ? triple.s : triple.o;
//				result.push( factory.getNode( term ) );
//			}
//
//			return result;		

		}




		/**
		 * 
		 * Returns one ( random order ) RDFNode obtained after following the arc.
		 * Or NULL if no value is found
		 * 
		 * @param arc
		 * @param inverse
		 * @return 
		 * 
		 */		
		public function any( arc:IRI, inverse:Boolean = false ):RDFNode
		{
				
			var arr:Array = all( arc, inverse );

			if ( arr.length == 0 )
				return null;
				
			return arr[ 0 ] as RDFNode;
		}




		override public function toString( ):String
		{
			return "RDFNode( " + rdfValue.toString( ) + " )";	
		}


	}
	

}